#ifndef _WX_ARRSTR_H
#define _WX_ARRSTR_H

#include "wx/defs.h"
#include "wx/string.h"

int wxCMPFUNC_CONV wxStringSortAscending( wxString*, wxString* );
int wxCMPFUNC_CONV wxStringSortDescending( wxString*, wxString* );

class wxArrayString {
  public:
    typedef int ( wxCMPFUNC_CONV *CompareFunction )( const wxString& first, const wxString& second );
    typedef int ( wxCMPFUNC_CONV *CompareFunction2 )( wxString* first, wxString* second );
    wxArrayString() { Init( false ); }
    wxArrayString( int autoSort ) { Init( autoSort != 0 ); }
    wxArrayString( size_t sz, const wxChar** a );
    wxArrayString( size_t sz, const wxString* a );
    wxArrayString( const wxArrayString& array );
    wxArrayString& operator=( const wxArrayString& src );
    ~wxArrayString();
    void Empty();
    void Clear();
    void Alloc( size_t nCount );
    void Shrink();
    size_t GetCount() const { return m_nCount; }
    bool IsEmpty() const { return m_nCount == 0; }
    size_t Count() const { return m_nCount; }
    wxString& Item( size_t nIndex ) const {
      wxASSERT_MSG( nIndex < m_nCount, wxT( "wxArrayString: index out of bounds" ) );
      return *( wxString * ) & ( m_pItems[nIndex] );
    }
    wxString& operator[]( size_t nIndex ) const { return Item( nIndex ); }
    wxString& Last() const {
      wxASSERT_MSG( !IsEmpty(), wxT( "wxArrayString: index out of bounds" ) );
      return Item( Count() - 1 );
    }
    int  Index( const wxChar *sz, bool bCase = true, bool bFromEnd = false ) const;
    size_t Add( const wxString& str, size_t nInsert = 1 );
    void Insert( const wxString& str, size_t uiIndex, size_t nInsert = 1 );
    void SetCount( size_t count );
    void Remove( const wxChar *sz );
    void RemoveAt( size_t nIndex, size_t nRemove = 1 );
    void Sort( bool reverseOrder = false );
    void Sort( CompareFunction compareFunction );
    void Sort( CompareFunction2 compareFunction );
    bool operator==( const wxArrayString& a ) const;
    bool operator!=( const wxArrayString& a ) const { return !( *this == a ); }
    typedef wxString value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type* iterator;
    typedef const value_type* const_iterator;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef int difference_type;
    typedef size_t size_type;

    class reverse_iterator {
        typedef wxString value_type;
        typedef value_type* pointer;
        typedef value_type& reference;
        typedef reverse_iterator itor;
        friend itor operator+( int o, const itor& it );
        friend itor operator+( const itor& it, int o );
        friend itor operator-( const itor& it, int o );
        friend difference_type operator -( const itor& i1, const itor& i2 );
      public:
        pointer m_ptr;
        reverse_iterator() : m_ptr( NULL ) { }
        reverse_iterator( pointer ptr ) : m_ptr( ptr ) { }
        reverse_iterator( const itor& it ) : m_ptr( it.m_ptr ) { }
        reference operator*() const { return *m_ptr; }
        pointer operator->() const { return m_ptr; }
        itor& operator++() { --m_ptr; return *this; }
        const itor operator++( int ) { reverse_iterator tmp = *this; --m_ptr; return tmp; }
        itor& operator--() { ++m_ptr; return *this; }
        const itor operator--( int ) { itor tmp = *this; ++m_ptr; return tmp; }
        bool operator ==( const itor& it ) const { return m_ptr == it.m_ptr; }
        bool operator !=( const itor& it ) const { return m_ptr != it.m_ptr; }
    };

    class const_reverse_iterator {
        typedef wxString value_type;
        typedef const value_type* pointer;
        typedef const value_type& reference;
        typedef const_reverse_iterator itor;
        friend itor operator+( int o, const itor& it );
        friend itor operator+( const itor& it, int o );
        friend itor operator-( const itor& it, int o );
        friend difference_type operator -( const itor& i1, const itor& i2 );
      public:
        pointer m_ptr;
        const_reverse_iterator() : m_ptr( NULL ) { }
        const_reverse_iterator( pointer ptr ) : m_ptr( ptr ) { }
        const_reverse_iterator( const itor& it ) : m_ptr( it.m_ptr ) { }
        const_reverse_iterator( const reverse_iterator& it ) : m_ptr( it.m_ptr ) { }
        reference operator*() const { return *m_ptr; }
        pointer operator->() const { return m_ptr; }
        itor& operator++() { --m_ptr; return *this; }
        const itor operator++( int ) { itor tmp = *this; --m_ptr; return tmp; }
        itor& operator--() { ++m_ptr; return *this; }
        const itor operator--( int ) { itor tmp = *this; ++m_ptr; return tmp; }
        bool operator ==( const itor& it ) const { return m_ptr == it.m_ptr; }
        bool operator !=( const itor& it ) const { return m_ptr != it.m_ptr; }
    };
    wxArrayString( const_iterator first, const_iterator last ) { Init( false ); assign( first, last ); }
    wxArrayString( size_type n, const_reference v ) { Init( false ); assign( n, v ); }
    void assign( const_iterator first, const_iterator last );
    void assign( size_type n, const_reference v ) { clear(); Add( v, n ); }
    reference back() { return *( end() - 1 ); }
    const_reference back() const { return *( end() - 1 ); }
    iterator begin() { return ( wxString * ) & ( m_pItems[0] ); }
    const_iterator begin() const { return ( wxString * ) & ( m_pItems[0] ); }
    size_type capacity() const { return m_nSize; }
    void clear() { Clear(); }
    bool empty() const { return IsEmpty(); }
    iterator end() { return begin() + GetCount(); }
    const_iterator end() const { return begin() + GetCount(); }
    iterator erase( iterator first, iterator last ) {
      size_t idx = first - begin();
      RemoveAt( idx, last - first );
      return begin() + idx;
    }
    iterator erase( iterator it ) { return erase( it, it + 1 ); }
    reference front() { return *begin(); }
    const_reference front() const { return *begin(); }
    void insert( iterator it, size_type n, const_reference v ) { Insert( v, it - begin(), n ); }
    iterator insert( iterator it, const_reference v = value_type() ) { size_t idx = it - begin(); Insert( v, idx ); return begin() + idx; }
    void insert( iterator it, const_iterator first, const_iterator last );
    size_type max_size() const { return INT_MAX; }
    void pop_back() { RemoveAt( GetCount() - 1 ); }
    void push_back( const_reference v ) { Add( v ); }
    reverse_iterator rbegin() { return reverse_iterator( end() - 1 ); }
    const_reverse_iterator rbegin() const;
    reverse_iterator rend() { return reverse_iterator( begin() - 1 ); }
    const_reverse_iterator rend() const;
    void reserve( size_type n );
    void resize( size_type n, value_type v = value_type() );
    size_type size() const { return GetCount(); }
  protected:
    void Init( bool autoSort );
    void Copy( const wxArrayString& src );
  private:
    void Grow( size_t nIncrement = 0 );
    void Free();
    void DoSort();
    size_t  m_nSize, m_nCount;
    wxChar  **m_pItems;
    bool m_autoSort;
};

class wxSortedArrayString : public wxArrayString {
  public:
    wxSortedArrayString() : wxArrayString( true ) { }
    wxSortedArrayString( const wxArrayString& array ) : wxArrayString( true ) { Copy( array ); }
};

class wxCArrayString {
  public:
    wxCArrayString( const wxArrayString& array )
      : m_array( array ), m_strings( NULL ) { }
    ~wxCArrayString() { delete[] m_strings; }

    size_t GetCount() const { return m_array.GetCount(); }
    wxString* GetStrings() {
      if( m_strings ) {
        return m_strings;
      }
      size_t count = m_array.GetCount();
      m_strings = new wxString[count];
      for( size_t i = 0; i < count; ++i ) {
        m_strings[i] = m_array[i];
      }
      return m_strings;
    }
    wxString* Release();
  private:
    const wxArrayString& m_array;
    wxString* m_strings;
};

#endif
